package com.gwnet.cabinet.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gwnet.cabinet.domian.Cabinet;
import com.gwnet.cabinet.domian.CabinetBox;
import com.gwnet.cabinet.domian.bo.CabinetAddBO;
import com.gwnet.cabinet.domian.bo.CabinetPageBO;
import com.gwnet.cabinet.mapper.CabinetMapper;
import com.gwnet.cabinet.service.CabinetBoxService;
import com.gwnet.cabinet.service.CabinetService;
import com.gwnet.common.core.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 外卖柜表 服务实现类
 * </p>
 *
 * @author WangLiang
 * @since 2024-07-23
 */
@Service
public class CabinetServiceImpl extends ServiceImpl<CabinetMapper, Cabinet> implements CabinetService {

    public final CabinetMapper cabinetMapper;
    public final CabinetBoxService boxService;

    @Autowired
    public CabinetServiceImpl(CabinetMapper cabinetMapper, CabinetBoxService boxService) {
        this.cabinetMapper = cabinetMapper;
        this.boxService = boxService;
    }

    @Override
    public IPage<Cabinet> page(CabinetPageBO pageBO){
        Page<Cabinet> page = Page.of(pageBO.getCurrent(),pageBO.getSize());

        LambdaQueryWrapper<Cabinet> queryWrapper = new LambdaQueryWrapper<>();
        // 设备ID
        if(StringUtils.isNotEmpty(pageBO.getDevSn())){
            queryWrapper.like(Cabinet::getDevSn,pageBO.getDevSn());
        }
        // 学校ID
        if(ObjectUtils.isNotEmpty(pageBO.getSchoolId())){
            queryWrapper.eq(Cabinet::getSchoolId,pageBO.getSchoolId());
        }
        // 启用状态 0.正常 1.禁用
        if(ObjectUtils.isNotEmpty(pageBO.getStatus())){
            queryWrapper.eq(Cabinet::getStatus,pageBO.getStatus());
        }
        // 圆心范围过滤
        // 设备型号
        if(ObjectUtils.isNotEmpty(pageBO.getModel())){
            queryWrapper.eq(Cabinet::getModel,pageBO.getModel());
        }

        Page<Cabinet> resultPage = cabinetMapper.selectPage(page, queryWrapper);
        return resultPage;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(CabinetAddBO addBO) {
        Cabinet cabinet = new Cabinet();
        BeanUtils.copyProperties(addBO,cabinet);

        // 箱格列表
        List<CabinetBox> boxList = new LinkedList<>();

        // 需要锁的箱格编号，用逗号隔开，例如："1,2,3,4"
        String lockBoxNos = addBO.getLockBoxNos();
        String[] lockBoxes = lockBoxNos.split(",");
        Set<String> lockBoxSet = new HashSet<>(Arrays.asList(lockBoxes));

        for (int i = 1; i <= cabinet.getTotalBox(); i++) {
            CabinetBox box = new CabinetBox();
            box.setBoxId(IdWorker.getId());
            box.setDevSn(cabinet.getDevSn());
            box.setBoxNo(i);
            box.setCreateTime(new Date());

            // 检查当前箱格编号是否在需要锁的编号列表中
            if (!lockBoxSet.contains(String.valueOf(i))) {
                // 不需要锁
                box.setBoxStatus(0);
            } else {
                // 需要锁
                box.setBoxStatus(1);
            }

            // 使用状态(0 空闲, 1 使用中, 2 超时)
            box.setUseState(0);
            boxList.add(box);
        }

        cabinet.setCreateTime(new Date());
        // 保存主表信息
        int cabinetCount = cabinetMapper.insert(cabinet);

        // 保存子表信息
        boolean flag = boxService.saveBatch(boxList);

        // 重新统计外卖柜状态
        cabinetMapper.reStatisticsBox(cabinet.getDevSn());

        return flag;
    }

    @Override
    public Cabinet view(String devSn) {
        Cabinet cabinet = cabinetMapper.selectById(devSn);
        return cabinet;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean delete(String devSn) {
        if(checkBox(devSn)){
            // 删除主表
            int count = cabinetMapper.deleteById(devSn);
            // 删除子表
            LambdaQueryWrapper<CabinetBox> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(CabinetBox::getDevSn,devSn);
            boolean remove = boxService.remove(queryWrapper);
            return count > 0;
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteBatch(String devSns) {
        if(checkBox(devSns)){
            // 删除主表
            String[] devSnArray = devSns.split(",");
            int count = cabinetMapper.deleteByIds(Arrays.asList(devSnArray));

            // 删除子表
            LambdaQueryWrapper<CabinetBox> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.in(CabinetBox::getDevSn,devSnArray);
            boolean remove = boxService.remove(queryWrapper);
            return count > 0;
        }
        return false;
    }


    /**
     * 检查是否哦包含未取出的箱格
     * @param devSns
     * @return
     */
    private Boolean checkBox(String devSns){
        String[] devSnArray = devSns.split(",");
        // 设备ID中有一个使用箱格不为0的就返回false
        LambdaQueryWrapper<Cabinet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Cabinet::getDevSn,devSnArray)
                .gt(Cabinet::getUseBox,0);
        Long count = cabinetMapper.selectCount(queryWrapper);
        if(count > 0){
            return false;
        }
        return true;
    }


}
